/**
 * @file    CTimerCommand.cpp
 * @date    2014-06-22
 * @author  Vladimir Prokopovich VProkopovich@gmail.com
 * @brief   Class CTimerCommand implementation file.
 */

#include "CTimerCommand.hpp"
#include "CTimerDispatcher.hpp"
#include "HWInterface.hpp"

CTimerCommand::CTimerCommand(void* pData, tCallbackFunction callback, const unsigned long long int& intervalRepeat, const unsigned long long int& intervalOnce, const eTimerType& type)
: mId(++gLastId)
, mpData(pData)
, mCallback(callback)
, mTimestamp(GetMicroSeconds())
, mIntervalRepeat(intervalRepeat)
, mIntervalOnce(intervalOnce)
, mType(type)
, mFiredOnce(false)
{
}

const unsigned long long int CTimerCommand::getNextFireTime() const
{
   unsigned long long int lastTime = 0U;
   unsigned long long int retVal = 0U;

   if (0U == mTimestamp)
   {
      lastTime = GetMicroSeconds();
   }
   else
   {
      lastTime = mTimestamp;
   }

   switch (mType)
   {
      case TIMER_TYPE_ONCE:
      {
         retVal = lastTime + mIntervalOnce;
         break;
      }
      case TIMER_TYPE_REPEAT:
      {
         retVal = lastTime + mIntervalRepeat;
         break;
      }
      case TIMER_TYPE_BOTH:
      {
         const unsigned long long int timeRepeat = lastTime + mIntervalRepeat;
         const unsigned long long int timeOnce = lastTime + mIntervalOnce;

         if (timeOnce <= timeRepeat)
         {
            retVal = timeOnce;
         }
         else
         {
            retVal = timeRepeat;
         }
         break;
      }
      case TIMER_TYPE_INVALID:
      {
         break;
      }
   }
   
   return retVal;
}

void CTimerCommand::timerFired()
{
   mTimestamp = getNextFireTime() + mIntervalRepeat/*GetMicroSeconds() - should be this method, but does not want to work under Raspberry*/;
   mFiredOnce = true;
   
   if (TIMER_TYPE_BOTH == mType)
   {
      mType = TIMER_TYPE_REPEAT;
   }
}